
package cn.donting.plugin.spring.boot.starter;

import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

@Slf4j
public class PluginClassLoader extends URLClassLoader {

    private static final String JAVA_PACKAGE_PREFIX = "java.";
    private static final String JAVAX_PACKAGE_PREFIX = "javax.";
    private static final String PLUGIN_PACKAGE_PREFIX = "cn.donting.plugin.spring.boot.starter.";
    private  final String RESOURCES_STARTS_WITH="cn.donting.plugin.spring.boot.starter".replaceAll("\\.",File.separator);
    public PluginClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
    }

    @Override
    public void addURL(URL url) {
        log.debug("Add '{}'", url);
        super.addURL(url);
    }

    public void addFile(File file) {
        try {
            addURL(file.getCanonicalFile().toURI().toURL());
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }


    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            if (name.startsWith(JAVA_PACKAGE_PREFIX) || name.startsWith(JAVAX_PACKAGE_PREFIX)) {
                return getParent().loadClass(name);
            }
            if (name.startsWith(PLUGIN_PACKAGE_PREFIX)) {
                return getParent().loadClass(name);
            }
            //查看是否加载过该类
            Class<?> loadedClass = findLoadedClass(name);
            if (loadedClass != null) {
                log.debug("findLoadedClass class '{}'", name);
                return loadedClass;
            }

            try {
                //尝试从插件中加载类
                Class<?> aClass = findClass(name);
                return aClass;
            } catch (Exception ex) {
                log.debug(ex.getMessage());
            }
            Class<?> aClass = getParent().loadClass(name);
            return aClass;
        }
    }

    @Override
    public URL getResource(String name) {
        //spring 中会通过 .class 字节码文件生成一些代理类，所以在遇到.calss 文件使其遵循双亲原则
        if (name.endsWith(".class")) {
            return super.getResource(name);
        } else {
            URL resource = findResource(name);
            return resource;
        }


//        if (resource != null) {
//            return resource;
//        } else {
//            return super.getResource(name);
//        }
    }

    //TODO:
    @Override
    public Enumeration<URL> getResources(String name) throws IOException {

        if (name.startsWith(RESOURCES_STARTS_WITH)) {
            List<URL> resources = new ArrayList<>();
            resources.addAll(Collections.list(super.getResources(name)));
            return Collections.enumeration(resources);
        } else {
            List<URL> resources = new ArrayList<>();
            resources.addAll(Collections.list(findResources(name)));
            return Collections.enumeration(resources);
        }


    }


}
